package com.xbq.oauth.security.sms;

import lombok.Getter;
import lombok.Setter;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;


@Getter
@Setter
public class SmsCodeAuthenticationProvider implements AuthenticationProvider {

    private UserDetailsService userDetailsService;

    /**
     * 短信验证逻辑
     * @param authentication
     * @return
     * @throws AuthenticationException
     */
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        SmsCodeAuthenticationToken authenticationToken = (SmsCodeAuthenticationToken) authentication;
        UserDetails user = userDetailsService.loadUserByUsername((String) authenticationToken.getPrincipal());

        if(user == null){
            //没有获取到用户信息
            throw new InternalAuthenticationServiceException("无法获取用户信息");
        }

        //认证交由UserDetails完成，完成之后，需要重新构造一个SmsCodeAuthenticationToken，调用两个参数的构造函数，来将认证设置成true
        SmsCodeAuthenticationToken authenticationResult = new SmsCodeAuthenticationToken(user,user.getAuthorities());
        //将未认证的SmsCodeAuthenticationToken的Details设置到已认证的SmsCodeAuthenticationToken里面去
        authenticationResult.setDetails(authenticationToken.getDetails());

        return authenticationResult;
    }


    /**
     * 判断传入的Authtication是否为SmsCodeAuthenticationToken类型
     * @param authentication
     * @return
     */
    @Override
    public boolean supports(Class<?> authentication) {
        return SmsCodeAuthenticationToken.class.isAssignableFrom(authentication);
    }
}
